﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using AirLinq.Meta;

namespace AirLinq {
	public class AirLinqDataReader<T> : IEnumerator<T> {
		private IDbCommand _com;
		private IDataReader _read;
		private readonly IMaterializer<T> _materializer;
		private T _current;
		private bool _disposed;
		public AirLinqDataReader(IDbCommand com, IMaterializer<T> materializer) {
			if (com == null) {
				throw new ArgumentNullException("com");
			}
			if (materializer == null) {
				throw new ArgumentNullException("materializer");
			}
			_com = com;
			_materializer = materializer;
		}
		private void CheckDisposed() {
			if (_disposed) {
				throw new ObjectDisposedException("");
			}
		}
		#region IEnumerator<T> Members
		public T Current {
			get {
				CheckDisposed();
				return _current;
			}
		}
		#endregion
		#region IDisposable Members
		public void Dispose() {
			try {
				if (_read != null) {
					_read.Dispose();
					_read = null;
				}
				if (_com != null) {
					_com.Dispose();
					_com = null;
				}
			} finally {
				_disposed = true;
			}
		}
		#endregion
		#region IEnumerator Members
		object System.Collections.IEnumerator.Current {
			get {
				return _current;
			}
		}
		public bool MoveNext() {
			CheckDisposed();
			if (_read == null) {
				_read = _com.ExecuteReader();
			}
			if (!_read.Read()) {
				_current = default(T);
				return false;
			}
			_current = _materializer.Create(_read);
			return true;
		}	
		public void Reset() {
			CheckDisposed();
			if (_read != null) {
				_read.Dispose();
				_read = null;
			}
		}
		#endregion
	}
}
